#include "plateau.h"

/*	DECLARATION	*/

int abs (int n);
int ecart (int a, int b);
int distance (Point a, Point b);
int longueur (Coup c);
int carre (int n);
int *casepoint (Grille *pGrille, Point p);
int *casegrille (Grille *pGrille, int x, int y);
int gety (int y);
bool align (Point a, Point b);
bool validc (Coup pCoup);
bool validg (Grille *pGrille, Coup c);
Joueur swaplayer (Joueur player);


/*	DEFINITION	*/

int abs (int n) {
	if (n<0)
		return -n;
	return n;
}

int ecart (int a, int b) { return abs(a - b); }

int distance (Point a, Point b) {
	return carre(ecart(a.x, b.x)) + carre(ecart(a.y, b.y));
}

int longueur (Coup c) {
	return distance(c.a, c.b);
}

int carre (int n) { return n * n; }

int *casepoint (Grille *pGrille, Point p) {
	return &pGrille->content[p.y * GRILLE_LARGEUR + p.x];
}

int *casegrille (Grille *pGrille, int x, int y) {
	return &pGrille->content[gety(y) + x];
}

int gety (int y) {
	return y * GRILLE_LARGEUR;
}

bool align (Point a, Point b) { return (a.x == b.x) || (a.y == b.y); }

bool validc (Coup c) { return align(c.a, c.b); }

bool validg (Grille *pGrille, Coup c) {
	return (*casepoint(pGrille, c.b) == VIDE)
		&& ((validc(c) && longueur(c) <= 4) || (longueur(c) == 1));
}

Joueur swaplayer (Joueur player) {
	if (player == P1) {
		return P2;
	} else {
		return P1;
	}
}



/* ------------------------------ */


void swap (Plateau *plato);
void deplacer (Plateau *plato, Point a, Point b);
void placer (Plateau *plato, Point p, int val);
void contaminer (Plateau *plato, Point p, Joueur player);
void set_nbplayer (Plateau *plato, Joueur player, int val);
void set_territoryplayer (Plateau *plato, Joueur player, int val);
void prendre_territoire (Plateau *plato, Point p, Joueur player);


void swap (Plateau *plato) { plato->player = swaplayer(plato->player); }

void deplacer (Plateau *plato, Point a, Point b) {
	*casepoint(&plato->grid, b) = *casepoint(&plato->grid, a);
	*casepoint(&plato->grid, a) = VIDE;
	*casepoint(&plato->territory, b) = plato->player;
}

void placer (Plateau *plato, Point p, int val) {
	*casepoint(&plato->grid, p) = val;
	*casepoint(&plato->territory, p) = val;
}

void contaminer (Plateau *plato, Point p, Joueur player) {
	int i, j;
	Joueur other;
	
	other = swaplayer(player);
	
	for (i = p.x - 1; i <= p.x + 1; i++)
	for (j = p.y - 1; j <= p.y + 1; j++) {
		if (i >= 0 && i < GRILLE_LARGEUR
			&& j >= 0 && j < GRILLE_HAUTEUR
			&& (i != p.x || j != p.y)) {
			if (*casegrille(&plato->grid, i, j) == other) {
				*casegrille(&plato->grid, i, j) = player;
				set_territoryplayer(plato, player, 1);
				set_territoryplayer(plato, other, -1);
				set_nbplayer(plato, player, 1);
				set_nbplayer(plato, other, -1);
			}
			if (*casegrille(&plato->territory, i, j) == VIDE) {
				*casegrille(&plato->territory, i, j) = player;
				set_territoryplayer(plato, player, 1);
			}
		}
	}
}

void prendre_territoire (Plateau *plato, Point p, Joueur player) {
	int i, j;
	Joueur other;
	
	other = swaplayer(player);
	
	for (i = p.x - 1; i <= p.x + 1; i++)
	for (j = p.y - 1; j <= p.y + 1; j++) {
		if (i >= 0 && i < GRILLE_LARGEUR
			&& j >= 0 && j < GRILLE_HAUTEUR
			&& (i != p.x || j != p.y)) {
			if (*casegrille(&plato->territory, i, j) == VIDE) {
				*casegrille(&plato->territory, i, j) = player;
				set_territoryplayer(plato, player, 1);
			}
		}
	}
}

void set_nbplayer (Plateau *plato, Joueur player, int val) {
	if (player == P1) {
		plato->nb_p1 += val;
	} else {
		plato->nb_p2 += val;
	}
}

void set_territoryplayer (Plateau *plato, Joueur player, int val) {
	if (player == P1) {
		plato->territory_p1 += val;
	} else {
		plato->territory_p2 += val;
	}
}

/* ------------------------------ */

void plateau_make (Plateau *plato) {
	int i;
	
	for (i=0; i < GRILLE_HAUTEUR * GRILLE_LARGEUR; i++) {
		(plato->grid).content[i] = VIDE;
		(plato->territory).content[i] = VIDE;
	}
	
	plato->player = P1;
}

void plateau_jouer (Plateau *plato, Coup c) {
	if (longueur(c) == 4) {
		deplacer(plato, c.a, c.b);
	} else {
		placer(plato, c.b, plato->player);
	}
	
	contaminer(plato, c.b, plato->player);
	
	swap(plato);
}

bool plateau_valid (Plateau *plato, Coup c) {
	return validg(&plato->grid, c) && plato->player == c.player;
}


void plateau_display (Plateau *plato) {
	int i, j;
	
	printf("Plateau :\n");
	
	for (j = 0; j < GRILLE_HAUTEUR; j++) {
		for (i = 0; i < GRILLE_LARGEUR; i++) {
			printf("%i", *casegrille(&plato->grid, i, j));
		}
		printf("\n");
	}
	
	printf("\nTerritoire :\n");
	
	for (j = 0; j < GRILLE_HAUTEUR; j++) {
		for (i = 0; i < GRILLE_LARGEUR; i++) {
			printf("%i", *casegrille(&plato->territory, i, j));
		}
		printf("\n");
	}
}


void plateau_placer (Plateau *plato, int x, int y, Joueur player) {
	Point p;
	
	p.x = x;
	p.y = y;
	placer(plato, p, player);
	prendre_territoire (plato, p, player);
}

